/**
 * ${table.comment!}基础信息的js文件
 * @license MIT
 * @Author ${author}
 * @Date ${date}
 * @description
 *      分页查询${table.comment!}基础信息
 *   需要<#if table.layuiTimeColumn??>初始化时间控件，</#if>初始化表格，再给页面添加一些事件
 *
 */
("use strict");
layui.define(function (exports) {
<#if fullComment>
    /**
     * @constant 表格列信息：
     * layui.table 的列信息是一个二维数组，这里仅定义一个简单表头，
     *     所以仅定义[[****]],二维数组的第一项
     * layui 部分表头配置项:
     *       title： 指表头的显示字符串， 通常是中文名称
     *       width/minWidth: 这一列宽度的像素点，推荐用minWidth，它可以自动适应内容
     *       field： 内容， layui.table 收到Object的数组作为数据源时，会在渲染每一行时遍历这个数组，这个field值的是Object里面对应的key了
     *       templet: 模板(Function或者Script块) 这一项的配置会覆盖上面的field. 在模版中使用变量 d 代表当前的Object
     * !!! 提示: 请不要将返回值的key设计成 length 否则在这个值为0时，layui.table将不能正常展示这个数据
     */
</#if>
    const cols = [
        [
            {
                title: "序号",
                width: 60,
                align: "center",
                type: "numbers"
            },
<#list table.fields as field>
    <#if !field.keyFlag >
            {
                field: "${field.propertyName}",
                title: "${field.alias}",
                <#if field.layuiMapper >
                 <#if fullComment>
                /**
                 * 这里使用 函数式的tpl对这一列的显示值进行优化。
                 * ( 如果返回的值就是想要展示的值，可以不要这一项 )
                 * 情况二： 这一项是有特殊定义的映射关系。在这里可以将定义的值"翻译"出来展示。
                 *      首先创建一个map，将特殊定义的内容以key - value的形式保存在这个临时变量中。(也可以放在外面做成公共的变量)
                 *      然后从变量d中获得当前的值 d.${field.propertyName} 在上面的临时变量中去找匹配的值
                 *      最后找到匹配的值就可以返回，这个tpl定义也就结束了。如果没有找到返回原有的值 d.${field.propertyName} 作为补充显示
                 */
                 </#if>
                templet: function(d){
                    let map = {
                 <#list field.source as source>
                        "${source.id}":"${source.name}",
                 </#list>
                    };
                    return map[d.${field.propertyName}] || d.${field.propertyName};
                },
                <#else>
                 <#if fullComment>
                /**
                 * 这里使用 函数式的tpl对这一列的显示值进行优化。
                 *  ( 如果返回的值就是想要展示的值，可以不要这一项 )
                 * 情况一：需要优化空值的展示 (数字 0 会被误认为是空值，但是数字0可能被定义成特殊意义进入情况二中，所以这里暂时不考虑这个情况)
                 *     直接进行boolean 判断 d.${field.propertyName}  是 true 还是 false
                 *     如果是true 就说明不是空值，遂返回原值 d.${field.propertyName}
                 *     如果是false 就说明是空值，遂返回 "/" 符号
                 */
                 </#if>
                templet: function(d){
                    if(!d.${field.propertyName}) return '/';
                    return d.${field.propertyName};
                },
                </#if>
                minWidth: 120,
            },
    </#if>
</#list>
<#if fullComment>
            /**
             *  这里使用 script标签的tpl给表格定义一个操作栏。
             *    ( 如果不需要操作栏，可以不要这一项 )
             *    ( 这一栏的width的值需要根据操作栏上面的按钮多寡灵活设置 )
             *    ( 按钮如果设置太多会影响使用，这个时候建议换成 dropdown  )
             *  fixed: "right"  指这一列是固定在右侧的； 同样的道理 fixed: "left" 指这一列固定在左侧
             *  toolbar: 传入一个script标签的id选择器 "#" + your id 就可以指定这个script里面的内容作为操作栏的渲染模板了
             */
</#if>
            {
                fixed: "right",
                title: "操作",
                toolbar: "#${table.entityName}-table-toolbar",
                width: 130,
            },
        ],
    ];
<#if fullComment>
    /**
     * @constant  模块名称
     * @description  用一个变量保存当前的模块名称
     */
</#if>
    const KEY = "${table.layuiEntityName}";

<#if fullComment>
    /**
     * @constant  id名称
     * @description  用一个变量保存对应的html里面div容器的id
     */
</#if>
    const ID = "${table.entityName}";

<#if fullComment>
    /**
     * @constant  请求地址
     * @description  用一个变量保存请求地址
     */
</#if>
    const URL = LAYER_BASE_URL + "<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>" + "/page${table.entityName}";

<#if fullComment>
    /**
     * @constant  删除地址
     * @description  用一个变量保存删除地址
     */
</#if>
    const DELETE_URL = LAYER_BASE_URL + "<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>" + "/delete${table.entityName}";

<#if fullComment>
 /**
 * @constant  导出excel地址
 * @description  用一个变量保存导出地址
 */
</#if>
    const EXPORT_URL = LAYER_BASE_URL + "<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>" + "/export${table.entityName}";

<#if fullComment>
 /**
 * @constant  导入excel地址
 * @description  用一个变量保存导入地址
 */
</#if>
    const EXCEL_URL = LAYER_BASE_URL + "<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>" + "/excel${table.entityName}";

<#if fullComment>
    /**
     * @namespace  ${table.layuiEntityName} 模块对象
     * @description  创建一个对象，用来将所有的操作最后注册到layui中
     */
</#if>
    let handler = {

<#if fullComment>
        /**
         * @method  主方法
         * @param {*} layero layui弹层的主体dom对象，是一个Jquery对象
         * @param {*} index layui弹层的编号，在执行关闭弹层等操作时被使用
         * @param {*} layopt 保留参数，在layui v2.8 + 这个代表layer对象
         * @param {*} option 对这个弹层的传入的参数
         * @description  这是一个入口方法，它会在layui.layer.open 的 success 回调中被调用
         */
<#else>
        /**
         * @method  程序的入口
         */
</#if>
        run: function (layero, index, layopt, option){
<#if table.layuiTimeColumn??>
<#if fullComment>
            /**
             * 初始化layui.laydate 时间控件
             */
 </#if>
            handler.initLayDate();
</#if>
<#if fullComment>
            /**
             * 初始化layui.table 表格
             */
</#if>
            handler.initTable();
<#if fullComment>
            /**
             * 初始化各项绑定事件
             */
</#if>
            handler.addListener();
        },
<#if table.layuiTimeColumn??>
<#if fullComment>
        /**
         * @method 渲染开始时间的时间选择框插件
         * @description laydate 使用 rander 方法来创建一个时间控件
         * @param {String/DOM} elem 渲染的目的地，既可以是文本框也可以是div;既可以传入选择器也可以html的dom元素。这里是使用id选择器的方式进行定义
         * @param {*} type 控件选择类型。默认值是: date。 一般的laydate默认是选择yyyy-MM-dd 格式的日期。这里使用默认值
         * @param {*} format 时间格式。默认值是: yyyy-MM-dd 。这里使用默认值
         * @param {*} value 默认值。默认值需要和 format 匹配。这里不设置，默认值就是空字符串
         * @param {*} done 日期时间选择完毕的回调函数
         * 除此之外还有很多别的配置项
         */
 </#if>
        initLayDate: function(){
<#if fullComment>
            /**
             * 渲染开始时间的时间选择框插件
             */
 </#if>
            layui.laydate.render({
                elem: "#" + ID + "-startTime",
                done: function done(value, date, endDate) {
<#if fullComment>
                    // TODO 开始时间变化后的回调函数可以放这里

                    /**
                     *  在日期的值切换时 {@linkplain handler#searchTable 刷新表格实例}
                     *   (这里需要强制回到第一页，所以传了true)
                     */
 </#if>
                    handler.searchTable(true);
                }
            });
<#if fullComment>
            /**
             * 渲染开始时间的时间选择框插件
             */
 </#if>
            layui.laydate.render({
                elem: "#" + ID + "-endTime",
                done: function done(value, date, endDate) {
<#if fullComment>
                    // TODO 结束时间变化后的回调函数可以放这里

                    /**
                     *  在日期的值切换时 {@linkplain handler#searchTable 刷新表格实例}
                     *   (这里需要强制回到第一页，所以传了true)
                     */
 </#if>
                    handler.searchTable(true);
                }
            });
        },
</#if>
<#if fullComment>
        /**
         * @method  初始化该弹层里面的table组件
         * @description 先创建一个新的table实例，然后查询数据更新表格信息
         */
</#if>
        initTable: function(){
            // 创建新的table实例
            handler.createTable(cols);
            // 查询数据，更新表格信息
            handler.searchTable(true);
        },

<#if fullComment>
        /**
         * @method  创建一个新的table实例
         * @param {*} cols {@linkplain cols 表头配置项}
         * @description 先创建一个新的table实例，将一些固定的配置项先放入实例中
         */
</#if>
        createTable: function(cols){
<#if fullComment>
           /**
            * 首次创建出一个layui.table的实例，并保存起来
            *    - 将表格的行信息传入，并放一个空数组进来，这样可以渲染出一个空的带表头的表格
            *  假如在接下来的请求数据出错时也可以有这个空表格占地方，不至于一片空白。
            * @description **(方法级渲染:)** 使用 layui.table.rander 方法来创建一个table实例
            * @param {*} elem 渲染的目的地，指向一个class中带有layui-table的table标签;既可以传入选择器也可以html的dom元素。这里是使用id选择器的方式进行定义
            * @param {*} data table渲染表格行数据的数据源。 此外也可以通过下面的 {@linkplain handler#searchTable url的方式异步请求获取数据源}
            * @param {*} cols {@linkplain cols 表头配置项}
            * @param {*} height 设置表格容器高度,数字的单位是px
            * @param {*} text 自定义文本，如空数据时的异常提示
            * @param {*} page 用于开启分页
            * @param {*} limit 每页显示的条数
            * @param {*} done 数据渲染完毕的回调函数
            * 除此之外还有很多别的配置项
            */
</#if>
            handler.tableInst = layui.table.render({
<#if fullComment>
                /**
                 * 传入待渲染的table的dom元素上面的id选择器
                 */
</#if>
                elem: "#" + ID + "-table",
<#if fullComment>
                /**
                 * 这里可以自定义分页上传的参数名称 默认的是 page 和 limit
                 */
</#if>
                // request: { pageName: "pageNo", limitName: "pageSize" },
<#if fullComment>
                /**
                 * 返回的状态码不是成功时，展示的提示信息
                 */
</#if>
                text: {
                  none: "暂无${table.comment}信息！"
                },
<#if fullComment>
                /**
                 * 传一个空数组占位置，layui.table也可以将数组作为数据源
                 */
</#if>
                data: [],
<#if fullComment>
                /**
                 * 上面定义好的表头信息
                 */
</#if>
                cols: cols,
<#if fullComment>
                /**
                 * 表格的高度，单位是px
                 */
</#if>
                height: 490,
<#if fullComment>
                /**
                 * 分页每一页的最大条数
                 */
</#if>
                limit: 10,
<#if fullComment>
                /**
                 * 分页参数，这里是copy的示例
                 */
</#if>
                page: {
                    groups: 3,
                    layout: ["prev", "page", "next", "skip", "count"],
                    jump: function jump(obj, first) {
                        if (!first) {
                        }
                    },
                },
                done: function (res, curr, count) {
<#if fullComment>
                    /**
                     * 记录下当前的页码
                     */
</#if>
                    handler.tableCurr = curr;

                    // TODO 表格渲染完毕的回调函数
                },
            });
        },
<#if fullComment>
        /**
         * @method 刷新表格信息
         * @param {*} flag 是否回到第一页 (true:回到第一页; false:保持当前页)
         * @description table 使用 reload 方法来更新表格的参数从而刷新表格
         *      @param {*} url 发送异步请求的 URL
         *      @param {*} method 请求的方式，默认：get 这里都使用 post
         *      @param {*} contentType 请求的内容编码类型。若要发送 json 内容，可设置： contentType: 'application/json'
         *      @param {*} where 请求的其他参数，这里是将表单里面的信息放入
         *      @param {*} loading 是否显示加载条。若为 false，则在切换分页时，不会出现加载条。必须设置了 url 属性才生效。
         *      更多参数在 {@linkplain handler#createTable 创建表格实例}时定义
         */
</#if>
        searchTable: function(flag = true){
<#if fullComment>
            /**
             * 组装请求参数
             */
</#if>
            let param = {
                url: URL,
                method: "post",
                contentType: "application/json",
                loading: true,
                where: {
<#if table.layuiNameColumn??>
                    name: $("#" + ID + "-name").val(),
</#if>
<#if table.layuiTimeColumn??>
                    startTime: $("#" + ID + "-startTime").val(),
                    endTime: $("#" + ID + "-endTime").val(),
</#if>
                },
                height: 490,
                limit: 10,
                page: {
                    curr: flag ? 1 : handler.tableCurr,
                },
            };
            layui.table.reload(ID + "-table", param);
        },
<#if fullComment>
        /**
         * @method 添加监听事件
         * @description 需要添加 搜索按钮和添加按钮点击事件，表单修改时刷新表格，表格操作栏点击事件
         */
</#if>
        addListener: function(){

<#if fullComment>
            /**
             * 添加搜索按钮的点击事件
             * @description 搜索按钮点击时，需要根据当前的表单信息 {@linkplain handler#searchTable 刷新表格实例}
             *       @method layui.form.on 这个是form表单提供的内置监听事件,它有两个参数
             *       @param {String} event(filter) 官方原话: event(filter) 是一个特定结构。event 为事件名，支持：select,checkbox,switch,radio,submit
             *                              由于之前给提交按钮添加了lay-submit的属性，所以这里可以使用 'submit' 这个 event, 括号里面在加上按钮的 lay-filter 属性。
             *                              连起来就是 'submit(${table.entityName}-submit)' 这个字符串了
             *       @param {Function} callback(obj) 回调函数 ，这个obj里面的field 属性就是表单信息了
             */
</#if>
            layui.form.on('submit(${table.entityName}-submit)', function (obj) {
<#if fullComment>
                /**
                 *  获取表单元素，执行接下来的操作
                 *   (这里在 刷新表格searchTable中 获取了表单上面的值，所以是直接调用的方法，没有用到这个事件提供的field)
                 */
</#if>
                // var field = obj.field;
<#if fullComment>
                /**
                 *  点击按钮调用方法来 {@linkplain handler#searchTable 刷新表格实例}
                 *   (这里需要强制回到第一页，所以传了true)
                 */
</#if>
                handler.searchTable(true);
                return false;
            });

<#if fullComment>
            /**
             * 添加导出按钮的点击事件
             * @description 导出按钮点击时，需要根据当前的表单信息 导出excel文件
             *       @method layui.form.on 这个是form表单提供的内置监听事件,它有两个参数
             *       @param {String} event(filter) 官方原话: event(filter) 是一个特定结构。event 为事件名，支持：select,checkbox,switch,radio,submit
             *                              由于之前给提交按钮添加了lay-submit的属性，所以这里可以使用 'submit' 这个 event, 括号里面在加上按钮的 lay-filter 属性。
             *                              连起来就是 'submit(${table.entityName}-export)' 这个字符串了
             *       @param {Function} callback(obj) 回调函数 ，这个obj里面的field 属性就是表单信息了
             */
</#if>
            layui.form.on('submit(${table.entityName}-export)', function (obj) {
<#if fullComment>
                /**
                 *  获取表单元素，执行接下来的操作
                 */
</#if>
                var field = obj.field;
                // TODO  文件导出更好的实现形式，下面仅为测试
                let exportUrl = EXPORT_URL + '?';
<#if table.layuiNameColumn??>
                exportUrl += 'name=' + $("#" + ID + "-name").val() + '&';
</#if>
<#if table.layuiTimeColumn??>
                exportUrl += 'startTime=' + $("#" + ID + "-startTime").val() + '&';
                exportUrl += 'endTime=' + $("#" + ID + "-endTime").val() + '&';
</#if>
                let request = new XMLHttpRequest();
                request.open('GET', exportUrl , true);
                request.responseType = 'arraybuffer';
                request.onload = function(){
                    let _data = request.response;
                    if(_data && 'byteLength' in _data && _data.byteLength == 0) return layui.layer.msg("下载失败!",{icon: 5});
                    let _url = window.URL.createObjectURL(new Blob([_data]));
                    var link = document.createElement("a");
                    link.href = _url
                    link.style.display='none';
                    // TODO 文件名称,需要由java生成,这里也可以指定
                    link.download = "excel.xlsx";
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                    window.URL.revokeObjectURL(_url);
                }
                request.send();
                return false;
            });


<#if table.layuiNameColumn??>
 <#if fullComment>
            /**
             *  在输入名称的时候，根据表单信息刷新表格
             */
 </#if>
            $("#" + ID + "-name").off("input propertychange").on("input propertychange", function(){
<#if fullComment>
                /**
                 *  输入名称时 {@linkplain handler#searchTable 刷新表格实例}
                 *   (这里需要强制回到第一页，所以传了true)
                 *  选择时间时的切换放在了 {@linkplain handler#initLayDate 初始化时间插件} 的回调函数中
                 */
 </#if>
                handler.searchTable(true);
            });
</#if>
<#if fullComment>
            /**
             *  点击添加按钮时，弹出添加${table.comment!}的弹出层
             */
</#if>
            $("#" + ID + "-add").off("click").on("click", function(){
                if (window.event) window.event.stopPropagation();
                layui.openLayer(KEY + "Add");
            });
<#if fullComment>
            /**
             * @method 文件上传渲染
             * @description upload 组件渲染，核心方法。
             *     除 elem 属性外,其他基础属性也可以直接写在元素的 lay-options="{}" 属性中. eg: <input type="button" class="layui-btn layui-btn-normal" id="ID-upload-demo-choose"  lay-options="{auto: false; multiple: true}" />
             * @param {String/DOM} elem 渲染的目的地,既可以传入选择器也可以html的dom元素。这里是使用id选择器的方式进行定义
             * @param {*} url 上传地址
             * @param {*} field 文件域的字段名 默认值是: file
             * @param {*} accept 允许上传时校验的文件类型  默认值: images  images 图片类型;video 视频类型;audio 音频类型;file 所有文件类型
             * @param {*} auto 是否选完文件后自动上传.若为 false,则需设置 bindAction 属性来指向其它按钮提交上传.  默认值是: true
             * @param {*} choose 是否选完文件后自动上传.若为 false,则需设置 bindAction 属性来指向其它按钮提交上传.  默认值是: true
             * @param {*} multiple 是否允许多文件上传  默认值是: false
             * @param {*} choose 选择文件后的回调函数
             * @param {*} done 执行单次文件上传请求后的回调函数
             * @param {*} error 执行上传请求出现异常的回调
             * 除此之外还有很多别的配置项
             */
</#if>
            layui.upload.render({
                elem: $("#" + ID + "-import"),
                url: EXCEL_URL,
                method: "POST",
                multiple: false,
                auto: true,
                accept: 'file',
                choose: function (obj) {
                    let files = (this.files = obj.pushFile());
                },
                done: function (res, index, upload) {
                    if (res.code == "200") {
                        layui.layer.msg("导入成功!",{icon: 6});
                        return delete this.files[index];
                    } else {
                        this.error(index, upload);
                    }
                },
                error: function (index, upload) {
                    layui.layer.msg("导入失败!",{icon: 6});
                    return delete this.files[index];
                },
            });

<#if fullComment>
            /**
             *  表格操作栏点击事件集合
             */
</#if>
            handler.fn = {
<#if fullComment>
                /**
                 *  点击修改按钮时，弹出修改${table.comment!}的弹出层。
                 *     由于不同的记录修改的内容也是不同的，所以如果在点击的时候这个修改的弹层已经弹出，需要先关闭了再打开新的
                 *     由于关闭弹层需要一点时间执行关闭动画之后才能完全关闭，所以这里会加上一个定时器
                 */
</#if>
                "updateRecord": function(obj){
                    if (window.event) window.event.stopPropagation();
                    let data = obj.data;
                    const updateID = KEY + "Update";
                    let wConfig = layui.windows.getPageDescribe(updateID);
                    if (wConfig && wConfig.index) {
                        layui.layer.close(wConfig.index);
                        setTimeout(function () {
                            layui.openLayer(updateID, { data: data, });
                        }, 500);
                    } else {
                        layui.openLayer(updateID, { data: data, });
                    }
                },
<#if fullComment>
                /**
                 *  点击删除按钮
                 */
</#if>
                "deleteByPid": function(obj){
                    if (window.event) window.event.stopPropagation();
                    let data = obj.data;
<#if table.layuiNameColumn??>
                    let _objName = data['${table.layuiNameColumn.propertyName}']
<#else>
                    let _objName = "";
</#if>
<#if fullComment>
                    /**
                     *  首先弹出一个询问是否删除${table.comment}记录，点击确定后再执行下面的操作。这样可以避免一些误删的操作
                     */
</#if>
                    layui.layer.confirm(
                        "您确认删除${table.comment}" + _objName + " 吗？",
                        function (index) {
                            layui.layer.close(index);
<#if fullComment>
                            /**
                             *  打开加载层。这里使用的是layui默认的加载层
                             */
</#if>
                            layui.layer.load();
                            $.ajax({
                                url: DELETE_URL,
                                data: JSON.stringify(data),
                                type: "POST",
                                dataType: "json",
                                contentType: "application/json",
                                success: function (res) {
<#if fullComment>
                                    /**
                                     *  关闭加载层。这里使用的是layui默认的加载层
                                     */
</#if>
                                    layui.layer.closeAll("loading");
                                    if(res.code == 200) {
                                        layui.layer.msg("删除成功！", { icon: 6 });
<#if fullComment>
                                        /**
                                         *  删除了之后需要{@linkplain handler#searchTable 刷新表格实例}
                                         *  为了防止当前页仅有一条记录，删除之后分页查回来空数据，这里传入 true 返回第一页
                                         */
</#if>
                                        handler.searchTable(true);
                                    }else{
                                        layui.layer.msg("删除失败！", { icon: 5 });
                                    }
                                    return;
                                },
                                error: function () {
<#if fullComment>
                                    /**
                                     *  关闭加载层。这里使用的是layui默认的加载层
                                     */
</#if>
                                    layui.layer.closeAll("loading");
                                    layui.layer.msg("删除失败！", { icon: 5 });
                                    return;
                                },
                            });
                        },
                        function (index) {
                            layui.layer.close(index);
                        }
                    );
                },
            };

<#if fullComment>
            /**
             *  表格操作栏事件绑定
             *  @description 在点击table表格行上面的操作栏是，执行上面指定的方法回调
             *       @method layui.table.on 与form模块相似,这个是table表单提供的内置监听事件,它有两个参数
             *       @param {String} event(filter)  这里面的event取 tool 指代的是绑定 表格行上面的操作栏
             *                              这里面的filter指代的是对应的layui.table的dom上面的 lay-filter 属性。
             *       @param {Function} callback(obj) 回调函数 ，这个obj里面的event 属性就是这个操作栏上面的 lay-event 属性;
             *                              这个obj里面的data就是这一行的数据源(在上面template里面介绍过的变量 d 了)
             */
</#if>
            layui.table.on('tool(' + ID + '-table)', function (obj) {
<#if fullComment>
                /**
                 *  evt: 获取到绑定按钮上面的lay-event属性，可以用来区分不同的事件类型
                 *  data: 这一行的数据源
                 */
</#if>
                var evt = obj.event;
                handler.fn[evt] && handler.fn[evt](obj);
            });
        },
    };

    /**
     *  将模块放入layui中
     */
    exports(KEY, handler);
});
